package org.sith.taskrunner.temp.tasks.distribution;

import java.util.ArrayList;
import java.util.List;

import org.sith.taskrunner.api.exceptions.TaskExecutionException;
import org.sith.taskrunner.api.exceptions.TaskInitException;
import org.sith.taskrunner.api.task.Task;

public class NormalDistributionTask implements
		Task<NormalDistributionInputData, NormalDistributionTaskResult> {

	private NormalDistributionInputData inputData;

	@Override
	public void init(NormalDistributionInputData inputData)
			throws TaskInitException {
		this.inputData = inputData;
	}

	@Override
	public NormalDistributionTaskResult executeTask()
			throws TaskExecutionException {
		double mathExpectation = getMathExpectation(inputData.getSequence());
		double dispersion = getDispertion(inputData.getSequence(), mathExpectation );
		double middleDeviation = getDeviation(dispersion);
		NormalDistributionTaskResult result = new NormalDistributionTaskResult();
		result.setMathExpectation(mathExpectation);
		result.setDispersion(dispersion);
		result.setDeviance(middleDeviation);
		return result;
	}

	/**
	 * Method to get math expectation of some sequence. m(x) = (x1+x2...+xn)/n
	 * 
	 * @param sequence
	 * @return math expectation
	 */
	private double getMathExpectation(List<Double> sequence) {
		if (sequence.size() == 0) {
			return 0;
		}
		double result = 0;
		for (double d : sequence) {
			result += d;
		}
		return result / sequence.size();
	}

	/**
	 * Method to get deviation of sequence use dispersion. s(x)= sqrt(d(x)).
	 * 
	 * @param dispertion
	 * @return deviation
	 */
	private double getDeviation(double dispertion) {
		if (dispertion < 0) {
			return 0;
		}
		return Math.sqrt(dispertion);
	}

	/**
	 * Method to get dispersion of some sequence d(x) = m(x*x) - m(x)*m(x);
	 * 
	 * @param sequence
	 * @param mathExpectation
	 * @return dispersion
	 */
	private double getDispertion(List<Double> sequence, double mathExpectation) {
		if (sequence.size() == 0) {
			return 0;
		}
		double result = 0;
		List<Double> sequnceInSquare = new ArrayList();
		int i;
		for (i = 0; i < sequence.size(); i++) {
			sequnceInSquare.add(sequence.get(i)*sequence.get(i));
			result = getMathExpectation(sequnceInSquare) - mathExpectation
					* mathExpectation;
		}
		return result;
	}
}
